package com.meiyuetao.myt.kuajing.service;

import java.io.StringReader;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException;

import lab.s2jh.core.dao.BaseDao;
import lab.s2jh.core.service.BaseService;
import lab.s2jh.core.util.DateUtils;

import org.apache.axis.client.Call;
import org.apache.axis.encoding.XMLType;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.meiyuetao.myt.kuajing.dao.YytFbOrderInfoDao;
import com.meiyuetao.myt.kuajing.dao.YytFbOrderInfoRspDao;
import com.meiyuetao.myt.kuajing.dao.YytOrderInfoDao;
import com.meiyuetao.myt.kuajing.dao.YytOrderInfoRspDao;
import com.meiyuetao.myt.kuajing.entity.YytFbOrderInfo;
import com.meiyuetao.myt.kuajing.entity.YytFbOrderInfoRsp;
import com.meiyuetao.myt.kuajing.entity.YytFbOrderInfoRsp.YytFbOrderRspEnum;
import com.meiyuetao.myt.kuajing.entity.YytFbOrderInfoRspDetail;
import com.meiyuetao.myt.kuajing.entity.YytFbOrderInfoRspDetail.OrderStsEnum;
import com.meiyuetao.myt.kuajing.entity.YytOrderDetailInfo;
import com.meiyuetao.myt.kuajing.entity.YytOrderInfo;
import com.meiyuetao.myt.kuajing.entity.YytOrderInfoRsp;
import com.meiyuetao.myt.kuajing.entity.YytOrderInfoRsp.YytOrderRspEnum;
import com.meiyuetao.myt.kuajing.entity.YytOrderInfoRspDetail;
import com.meiyuetao.myt.kuajing.entity.YytOrderInfoRspDetail.YytOrderRspDetailEnum;
import com.meiyuetao.myt.sale.dao.BoxOrderDetailDao;
import com.meiyuetao.myt.sale.entity.BoxOrder;
import com.meiyuetao.myt.sale.entity.BoxOrder.BoxOrderStatusEnum;
import com.meiyuetao.myt.sale.entity.BoxOrder.YytPostStatusEnum;
import com.meiyuetao.myt.sale.entity.BoxOrderDetail;
import com.meiyuetao.myt.sale.entity.BoxOrderDetail.BoxOrderDetailStatusEnum;
import com.meiyuetao.myt.sale.entity.BoxOrderDetailCommodity;
import com.meiyuetao.myt.sale.service.BoxOrderService;

@Service
@Transactional
public class YytOrderInfoService extends BaseService<YytOrderInfo, Long> {

    @Autowired
    private YytOrderInfoDao yytOrderInfoDao;
    @Autowired
    private YytOrderInfoRspDao yytOrderInfoRspDao;
    @Autowired
    private YytFbOrderInfoDao yytFbOrderInfoDao;
    @Autowired
    private YytFbOrderInfoRspDao yytFbOrderInfoRspDao;
    @Autowired
    private BoxOrderService boxOrderService;
    @Autowired
    private BoxOrderDetailDao boxOrderDetailDao;

    @Override
    protected BaseDao<YytOrderInfo, Long> getEntityDao() {
        return yytOrderInfoDao;
    }

    /**
     * 传订单至怡亚通
     * 
     * @param boxOrder
     */
    public void postPoForOut(BoxOrder boxOrder) {
        String objectStr = generateOrderInfoXml(boxOrder);
        String result = postToYyt("GetPoForOutXmlService", "GetPoForOutXmlServiceRequest", objectStr);
        if (StringUtils.isNotBlank(result)) {
            YytOrderInfo yytOrderInfo = generateYytOrderInfoByBoxOrder(boxOrder);
            recordPoInfo(yytOrderInfo, result);
        }

    }

    private void recordPoInfo(YytOrderInfo yytOrderInfo, String result) {
        yytOrderInfoDao.save(yytOrderInfo);
        Document doc = buildDocByStr(result);
        YytOrderInfoRsp yoir = new YytOrderInfoRsp();
        yoir.setYytOrderInfo(yytOrderInfo);
        BoxOrder boxOrder = yytOrderInfo.getBoxOrder();
        NodeList nodes = doc.getElementsByTagName("polist");
        if (nodes.getLength() > 0) {
            Node polistNode = nodes.item(0);
            for (int i = 0; i < polistNode.getChildNodes().getLength(); i++) {
                Node node = polistNode.getChildNodes().item(i);
                if ("status".equals(node.getNodeName())) {
                    yoir.setStatus(YytOrderRspEnum.valueOf("Y_" + node.getTextContent()));
                    boxOrder.setYytPostStatus(YytPostStatusEnum.valueOf("Y_" + node.getTextContent()));
                    boxOrderService.save(boxOrder);
                }
                if ("message".equals(node.getNodeName())) {
                    yoir.setMessage(node.getTextContent());
                }

            }
        }
        List<YytOrderInfoRspDetail> yytOrderInfoRspDetails = yoir.getYytOrderInfoRspDetails();
        NodeList poNodes = doc.getElementsByTagName("po");
        for (int i = 0; i < poNodes.getLength(); i++) {
            Node polistNode = poNodes.item(i);
            YytOrderInfoRspDetail yoird = new YytOrderInfoRspDetail();
            yoird.setOrderInfoRsp(yoir);
            for (int j = 0; j < polistNode.getChildNodes().getLength(); j++) {
                Node node = polistNode.getChildNodes().item(j);
                if ("sts".equals(node.getNodeName())) {
                    yoird.setSts(YytOrderRspDetailEnum.valueOf("Y_" + node.getTextContent()));
                }
                if ("pocode".equals(node.getNodeName())) {
                    yoird.setPocode(node.getTextContent());
                }
                if ("message".equals(node.getNodeName())) {
                    yoird.setMessage(node.getTextContent());
                }
            }
            yytOrderInfoRspDetails.add(yoird);
        }
        yytOrderInfoRspDao.save(yoir);
        for (YytOrderInfoRspDetail item : yytOrderInfoRspDetails) {
            String pocode = item.getPocode();
            boxOrder = boxOrderService.findByOrderSeq(pocode);
            boxOrder.setYytPostStatus(YytPostStatusEnum.valueOf(item.getSts().name()));
            boxOrderService.save(boxOrder);
        }
    }

    /**
     * 从怡亚通上更新物流信息
     * 
     * @param orderSeqs
     */

    public String sendFbOutInfo(String orderSeqs) {
        String objectStr = generateSendFbOrderInfoXml(orderSeqs);
        String result = postToYyt("SendFbOutInfoXmlService", "SendFbOutInfoXmlServiceRequest", objectStr);
        if (StringUtils.isNotBlank(result)) {
            YytFbOrderInfo yytFbOrderInfo = generateFbOrderInfo(orderSeqs);
            recordFbPoInfo(yytFbOrderInfo, result);
        }
        return result;
    }

    private void recordFbPoInfo(YytFbOrderInfo yytFbOrderInfo, String result) {
        yytFbOrderInfoDao.save(yytFbOrderInfo);
        Document doc = buildDocByStr(result);
        YytFbOrderInfoRsp yfoir = new YytFbOrderInfoRsp();
        NodeList nodes = doc.getElementsByTagName("fbinfo");
        if (nodes.getLength() > 0) {
            Node polistNode = nodes.item(0);
            for (int i = 0; i < polistNode.getChildNodes().getLength(); i++) {
                Node node = polistNode.getChildNodes().item(i);
                if ("status".equals(node.getNodeName())) {
                    yfoir.setStatus(YytFbOrderRspEnum.valueOf("Y_" + node.getTextContent()));
                }
                if ("maxnum".equals(node.getNodeName())) {
                    yfoir.setMaxnum(Long.valueOf(node.getTextContent()));

                }
                if ("message".equals(node.getNodeName())) {
                    yfoir.setMessage(node.getTextContent());
                }
            }
        }
        List<YytFbOrderInfoRspDetail> yytOrderInfoRspDetails = yfoir.getYytFbOrderInfoRspDetails();
        NodeList poNodes = doc.getElementsByTagName("orderinfo");
        for (int i = 0; i < poNodes.getLength(); i++) {
            Node polistNode = poNodes.item(i);
            YytFbOrderInfoRspDetail yoird = new YytFbOrderInfoRspDetail();
            for (int j = 0; j < polistNode.getChildNodes().getLength(); j++) {
                Node node = polistNode.getChildNodes().item(j);
                if ("seno".equals(node.getNodeName())) {
                    yoird.setSeno(Long.valueOf(node.getTextContent()));
                }
                if ("pocode".equals(node.getNodeName())) {
                    yoird.setPocode(node.getTextContent());
                }
                if ("sts".equals(node.getNodeName())) {
                    yoird.setSts(OrderStsEnum.valueOf(node.getTextContent()));
                }
                if ("dealdate".equals(node.getNodeName())) {
                    yoird.setDealDate(DateUtils.parseDate(node.getTextContent()));
                }
                if ("expresscompany".equals(node.getNodeName())) {
                    yoird.setExpresscompany(node.getTextContent());
                }
                if ("expresscode".equals(node.getNodeName())) {
                    yoird.setExpresscode(node.getTextContent());
                }
            }
            yytOrderInfoRspDetails.add(yoird);
        }
        yytFbOrderInfoRspDao.save(yfoir);
        for (YytFbOrderInfoRspDetail item : yytOrderInfoRspDetails) {
            String pocode = item.getPocode();
            BoxOrder boxOrder = boxOrderService.findByOrderSeq(pocode);
            if (StringUtils.isNotBlank(item.getExpresscode()) && !item.getExpresscode().equals(boxOrder.getYytLogisticsNo())) {
                boxOrder.setYytLogisticsNo(item.getExpresscode());
                boxOrder.setYytLogisticsName(item.getExpresscompany());
                for (BoxOrderDetail boxOrderDetail : boxOrder.getBoxOrderDetails()) {
                    boxOrderDetail.setDeliveryFinishTime(new Date());
                    boxOrderDetail.setLogisticsNo(item.getExpresscode());
                    boxOrderDetail.setLogisticsName(item.getExpresscompany());
                    boxOrderDetail.setOrderDetailStatus(BoxOrderDetailStatusEnum.S50DF);
                    boxOrderDetailDao.save(boxOrderDetail);
                }
                boxOrder.setDeliveryFinishTime(new Date());
                boxOrder.setOrderStatus(BoxOrderStatusEnum.S50DF);
                boxOrderService.save(boxOrder);
            }

        }
    }

    private Document buildDocByStr(String result) {
        StringReader sr = new StringReader(result);
        InputSource is = new InputSource(sr);
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        Document doc = null;
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            doc = builder.parse(is);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return doc;
    }

    private String postToYyt(String methodName, String pName, String objectStr) {
        String result = "";
        org.apache.axis.client.Service site = new org.apache.axis.client.Service();
        Call call;
        Object[] object = new Object[1];
        object[0] = objectStr;// Object是用来存储方法的参数
        try {
            call = (Call) site.createCall();
            call.setTargetEndpointAddress(orderSendUrl);// 远程调用路径
            call.setOperationName(methodName);// 调用的方法名

            // 设置参数名:
            call.addParameter(pName, // 参数名
                    XMLType.XSD_STRING,// 参数类型:String
                    ParameterMode.IN);// 参数模式：'IN' or 'OUT'
            // 设置返回值类型：
            call.setReturnType(XMLType.XSD_STRING);// 返回值类型：String
            result = (String) call.invoke(object);// 远程调用

        } catch (ServiceException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return result;
    }

    private String generateOrderInfoXml(BoxOrder boxOrder) {
        String xmlString = "<polist>" + "<fbtype>GETPO</fbtype>" + "<shiptocode>" + shopToCode + "</shiptocode>" + "<pos>" + "<po>" + "<pocode>" + boxOrder.getOrderSeq()
                + "</pocode>" + "<podate>" + DateUtils.formatDate(boxOrder.getOrderTime()) + "</podate>" + "<shiptoname>" + boxOrder.getReceivePerson() + "</shiptoname>"
                + "<mobile>" + boxOrder.getMobilePhone() + "</mobile>" + "<tel></tel>" + "<city>" + boxOrder.getDeliveryCity() + "</city>" + "<address>"
                + boxOrder.getDeliveryAddr() + "</address>" + "<remark1>" + boxOrder.getCustomerMemo() + "</remark1>" + "<remark2></remark2>" + "<expresscompany></expresscompany>"
                + "<expresscode></expresscode>" + "<buyerid>" + boxOrder.getCustomerProfile().getDisplay() + "</buyerid>" + "<customcode>" + boxOrder.getCustomCode()
                + "</customcode>" + "<pols>";
        for (BoxOrderDetailCommodity item : boxOrder.getBoxOrderDetailCommodities()) {
            xmlString += "<pol>" + " <shopid>" + shopId + "</shopid>" + " <shopname>" + shopName + "</shopname>" + "<goodsid>" + item.getCommodity().getSku() + "</goodsid>"
                    + "<barcode>" + item.getCommodity().getSku() + "</barcode>" + "<goodsname>" + item.getCommodity().getTitle() + "</goodsname>" + "<qty>" + item.getQuantity()
                    + "</qty>" + "<price>" + item.getPrice() + "</price>" + "<unitname>" + item.getCommodity().getSpec() + "</unitname>" + "</pol>";
        }
        xmlString += "</pols>" + "</po>" + "</pos>" + "</polist>";
        return xmlString;
    }

    private YytFbOrderInfo generateFbOrderInfo(String orderSeqs) {
        YytFbOrderInfo yfoi = new YytFbOrderInfo();
        yfoi.setFbType("SENDFBPO");
        yfoi.setShipToCode(shopToCode);
        yfoi.setPoCodes(orderSeqs);
        return yfoi;
    }

    private YytOrderInfo generateYytOrderInfoByBoxOrder(BoxOrder boxOrder) {
        YytOrderInfo yoi = new YytOrderInfo();
        yoi.setBoxOrder(boxOrder);
        yoi.setFbType("GETPO");
        yoi.setShipToCode(shopToCode);
        yoi.setPocode(boxOrder.getOrderSeq());
        yoi.setPodate(DateUtils.formatDate(boxOrder.getOrderTime()));
        yoi.setShiptoname(boxOrder.getReceivePerson());
        yoi.setMobile(boxOrder.getMobilePhone());
        yoi.setCity(boxOrder.getDeliveryCity());
        yoi.setAddress(boxOrder.getDeliveryAddr());
        yoi.setRemark1(boxOrder.getMemo());
        yoi.setBuyerid(boxOrder.getCustomerProfile().getDisplay());
        yoi.setCustomcode(boxOrder.getCustomCode());
        List<YytOrderDetailInfo> orderDetailInfos = yoi.getOrderDetailInfos();
        for (BoxOrderDetailCommodity item : boxOrder.getBoxOrderDetailCommodities()) {
            YytOrderDetailInfo yodi = new YytOrderDetailInfo();
            yodi.setOrderInfo(yoi);
            yodi.setShopId(shopId);
            yodi.setShopName(shopName);
            yodi.setGoodsId(item.getCommodity().getTaxCode());
            yodi.setBarcode(item.getCommodity().getTaxCode());
            yodi.setGoodsName(item.getCommodity().getTitle());
            yodi.setQty(item.getQuantity());
            yodi.setPrice(item.getPrice());
            yodi.setUnitName(item.getCommodity().getSpec());
            orderDetailInfos.add(yodi);
        }

        return yoi;
    }

    private String generateSendFbOrderInfoXml(String orderSeqs) {
        String xmlString = "<fbinfo><fbtype>SENDFBPO</fbtype>" + "<shiptocode>" + shopToCode + "</shiptocode>" + "<pocodes>" + orderSeqs + "</pocodes>" + "</fbinfo>";
        return xmlString;
    }

    @Value("${yyt.orderSendUrl}")
    private String orderSendUrl;
    @Value("${yyt.shopId}")
    private String shopId;
    @Value("${yyt.shopToCode}")
    private String shopToCode;
    @Value("${yyt.shopName}")
    private String shopName;

    public String getOrderSendUrl() {
        return orderSendUrl;
    }

    public void setOrderSendUrl(String orderSendUrl) {
        this.orderSendUrl = orderSendUrl;
    }

    public String getShopId() {
        return shopId;
    }

    public void setShopId(String shopId) {
        this.shopId = shopId;
    }

    public String getShopToCode() {
        return shopToCode;
    }

    public void setShopToCode(String shopToCode) {
        this.shopToCode = shopToCode;
    }

    public String getShopName() {
        return shopName;
    }

    public void setShopName(String shopName) {
        this.shopName = shopName;
    }

}
